<!DOCTYPE html>
<html lang="zh-Hans-CN">

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <link rel="stylesheet" type="text/css" href="css/modern-norm.min.css" />
    <link rel="stylesheet" type="text/css" href="css/prism.min.css" />
    <link rel="stylesheet" type="text/css" href="css/katex.min.css" />
    <link rel="stylesheet" type="text/css" href="css/wolai.css" />
    <title>协程，线程和进程的区别 - wolai 笔记</title>
    <link rel="shortcut icon"
        href="data:image/svg+xml,%3Csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 800 800&apos;%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:%23fff;%7D%3C/style%3E%3C/defs%3E%3Cg%3E%3Cpath class=&apos;cls-1&apos; d=&apos;M610.08,0c66,0,90,6.88,114.13,19.79a134.62,134.62,0,0,1,56,56l2.28,4.4C793.93,103,800,127.88,800,189.92V610.08l-.08,11.56c-.78,57.38-7.58,79.89-19.71,102.57a134.62,134.62,0,0,1-56,56l-4.4,2.28C697,793.93,672.12,800,610.08,800H189.92l-11.56-.08c-57.38-.78-79.89-7.58-102.57-19.71a134.62,134.62,0,0,1-56-56l-2.28-4.4C6.44,697.75.4,673.72,0,616L0,189.92c0-66,6.88-90,19.79-114.13a134.62,134.62,0,0,1,56-56l4.4-2.28C102.25,6.44,126.28.4,184,0Z&apos;/%3E%3Cpath d=&apos;M610.08,0c66,0,90,6.88,114.13,19.79a134.62,134.62,0,0,1,56,56l2.28,4.4C793.93,103,800,127.88,800,189.92V610.08l-.08,11.56c-.78,57.38-7.58,79.89-19.71,102.57a134.62,134.62,0,0,1-56,56l-4.4,2.28C697,793.93,672.12,800,610.08,800H189.92l-11.56-.08c-57.38-.78-79.89-7.58-102.57-19.71a134.62,134.62,0,0,1-56-56l-2.28-4.4C6.44,697.75.4,673.72,0,616L0,189.92c0-66,6.88-90,19.79-114.13a134.62,134.62,0,0,1,56-56l4.4-2.28C102.25,6.44,126.28.4,184,0Zm4.72,88.9H185.2L172.42,89c-32.78.62-43.68,3.24-54.71,9.14a45.84,45.84,0,0,0-19.54,19.54c-6.61,12.36-9.11,24.55-9.27,67.49V614.8L89,627.58c.62,32.78,3.24,43.68,9.14,54.71a45.84,45.84,0,0,0,19.54,19.54c12.36,6.61,24.55,9.11,67.49,9.27H610.08c46.79,0,59.41-2.44,72.21-9.28a45.84,45.84,0,0,0,19.54-19.54c6.61-12.36,9.11-24.55,9.27-67.49V189.92c0-46.79-2.44-59.41-9.28-72.21a45.84,45.84,0,0,0-19.54-19.54C669.93,91.56,657.74,89.06,614.8,88.9ZM233.33,493.33A73.34,73.34,0,1,1,160,566.67,73.35,73.35,0,0,1,233.33,493.33Z&apos;/%3E%3C/g%3E%3C/svg%3E">
    </link>
</head>

<body class="less-lead">
    <header>
        <div class="image"></div>
        <div class="title">
            <div class="banner">
                <div class="icon"></div>
            </div>
            <div data-title="协程，线程和进程的区别" class="main-title"></div>
        </div>
    </header>
    <article>
        <ul class="wolai-block">
            <li class="block-ref">
                <div class="marker"><svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
                        xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 14.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z"></path>
                    </svg></div><span class="inline-wrap">对操作系统来说，</span><span
                    class="inline-wrap"><b>线程是最小的执行单元，进程是最小的资源管理单元。</b></span><span class="inline-wrap">
                    无论进程还是线程，都是由操作系统所管理的。</span>
                <div class="decorator"></div>
                <div class="wolai-block wolai-text">
                    <div><span class="inline-wrap">协程</span><span
                            class="inline-wrap"><code>(Coroutines)</code></span><span
                            class="inline-wrap">是一种比线程更加轻量级的存在</span></div>
                </div>
            </li>
        </ul>
        <h2 class="wolai-block"><span class="inline-wrap">1</span><span class="inline-wrap"><b>进程</b></span></h2>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">一个进程好比是一个程序，它是</span><span class="inline-wrap"><b>资源分配的最小单位</b></span><span
                    class="inline-wrap"> 。也是<span class="jill"></span>CPU<span
                        class="jill"></span>的最小工作单元，就是说操作系统同一时刻执行的进程数不会超过核心数。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">电脑中有许多进程需要处于「同时」开启的状态，而利用<span class="jill"></span>CPU<span
                        class="jill"></span>在进程间的快速切换，可以实现「同时」运行多个程序。而进程切换则意味着需要保留进程切换前的状态，以备切换回去的时候能够继续接着工作。
                    所以</span><span class="inline-wrap"><b>进程拥有自己的地址空间，全局变量，文件描述符，各种硬件等等资源</b></span><span
                    class="inline-wrap">。操作系统通过调度<span class="jill"></span>CPU<span
                        class="jill"></span>去执行进程的记录、回复、切换等等。</span></div>
        </div>
        <h2 class="wolai-block"><span class="inline-wrap">2</span><span class="inline-wrap"><b>线程</b></span></h2>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">线程是一个程序执行过程中的最小单元，一个程序可能包含多个线程，这多个线程共享进程的所有资源。每个线程执行不同的任务来提高程序的运行效率。</span>
            </div>
        </div>
        <h2 class="wolai-block"><span class="inline-wrap">3</span><span class="inline-wrap"><b>进程与线程的区别</b></span></h2>
        <ol class="wolai-block">
            <li>
                <div class="marker"></div><span class="inline-wrap">进程是<span class="jill"></span>CPU<span
                        class="jill"></span>资源分配的基本单位，线程是独立运行和独立调度的基本单位（CPU<span class="jill"></span>上真正运行的是线程）。</span>
            </li>
            <li>
                <div class="marker"></div><span class="inline-wrap">进程拥有自己的资源空间，一个进程包含若干个线程，线程与<span
                        class="jill"></span>CPU<span class="jill"></span>资源分配无关，多个线程共享同一进程内的资源。</span>
            </li>
            <li>
                <div class="marker"></div><span class="inline-wrap">线程的调度与切换比进程快很多。</span>
            </li>
        </ol>
        <h2 class="wolai-block"><span class="inline-wrap">4<span class="jill"></span>为什么要有线程？</span></h2>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap"><b>线程的出现就是为了提高单位时间内<span class="jill"></span>CPU<span
                            class="jill"></span>的利用率。</b></span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">任务一般分为两种：CPU<span class="jill"></span>密集型和<span class="jill"></span>IO<span
                        class="jill"></span>密集型。</span></div>
        </div>
        <ul class="wolai-block">
            <li>
                <div class="marker"><svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
                        xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 14.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z"></path>
                    </svg></div><span class="inline-wrap">CPU<span class="jill"></span>密集型任务对<span
                        class="jill"></span>CPU<span class="jill"></span>的利用率较高</span>
            </li>
            <li>
                <div class="marker"><svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
                        xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 14.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z"></path>
                    </svg></div><span class="inline-wrap">IO<span class="jill"></span>密集型的程序因为包含了大量的<span
                        class="jill"></span>IO<span class="jill"></span>操作，所以其状态在就绪、运行、阻塞之前频繁切换。</span>
            </li>
        </ul>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">随着程序的功能越来越复杂，程序更加偏向于<span class="jill"></span>IO<span
                        class="jill"></span>密集型，而<span class="jill"></span>IO<span
                        class="jill"></span>密集型任务也就是无法即使完成任务而带来大量的上下文切换。而进程之间上下文切换的代价是比较高的。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">因此为了使用更小的粒度提高进程单位时间的<span class="jill"></span>CPU<span
                        class="jill"></span>利用率，就有了线程的概念。</span><span class="inline-wrap"><b>进程作为线程的容器</b></span><span
                    class="inline-wrap">，可以按不同的功能，或想达到更高效率（如多个<span class="jill"></span>IO<span
                        class="jill"></span>线程）的同一功能，可以考虑产生多个线程。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">因为在<span class="jill"></span>CPU<span
                        class="jill"></span>切换到本进程的时间段时，由于线程间共享进程的上下文，线程切换只需要切换线程的上下文，而不需要切换另一片内存或者寄存器资源，在功能并行执行的同时降低了开销。</span>
            </div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">但是需要</span><span class="inline-wrap"><b>注意</b></span><span
                    class="inline-wrap">的是</span><span class="inline-wrap"><b>开更多的线程不会导致本进程得到更多<span
                            class="jill"></span>CPU<span class="jill"></span>的青睐</b></span><span
                    class="inline-wrap">!多线程只能提高进程在执行过程中的<span class="jill"></span>CPU<span
                        class="jill"></span>利用率。</span></div>
        </div>
        <h2 class="wolai-block"><span class="inline-wrap">5<span class="jill"></span>什么是协程？</span></h2>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">虽然线程大幅的提高了<span class="jill"></span>CPU<span
                        class="jill"></span>的效率，且能够设置一定的优先级，但是线程的资源片分配还是由<span class="jill"></span>CPU<span
                        class="jill"></span>来管理的。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">那么能不能人为管理线程的资源分配（切换）呢？协程在语言层面实现了这一点。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">如同一个进程可以有很多线程一样，一个线程可以有很多协程。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">但是，协程不是被操作系统所管理的，</span><span class="inline-wrap"><b>没有改变<span
                            class="jill"></span>CPU<span class="jill"></span>最小执行单元是线程</b></span><span
                    class="inline-wrap">，协程是完全由程序所控制的（用户态执行），不会产生上下文切换。</span></div>
        </div>
        <div class="wolai-block wolai-text">
            <div><span class="inline-wrap">目前</span><span class="inline-wrap"><b>只有部分语言实现了协程</b></span><span
                    class="inline-wrap">：</span></div>
            <ol class="wolai-block">
                <li>
                    <div class="marker"></div><span class="inline-wrap"><code>python</code></span><span
                        class="inline-wrap">的</span><span class="inline-wrap"><code>yield/send</code></span><span
                        class="inline-wrap">，当协程执行到<span class="jill"></span>yield<span
                            class="jill"></span>关键字时，会暂停在那一行，等到主线程调用</span><span
                        class="inline-wrap"><code>send</code></span><span
                        class="inline-wrap">方法发送了数据，协程才会接到数据继续执行。</span>
                </li>
                <li>
                    <div class="marker"></div><span class="inline-wrap"><code>Lua</code></span><span
                        class="inline-wrap">从<span class="jill"></span>5.0<span
                            class="jill"></span>版本开始使用协程，通过扩展库</span><span
                        class="inline-wrap"><code>coroutine</code></span><span class="inline-wrap">来实现。</span>
                </li>
                <li>
                    <div class="marker"></div><span class="inline-wrap"><code>Go</code></span><span
                        class="inline-wrap">语言对协程的实现非常强大而简洁，可以轻松创建成百上千个协程并发执行。</span>
                </li>
                <li>
                    <div class="marker"></div><span class="inline-wrap"><code>Java</code></span><span
                        class="inline-wrap">语言并没有对协程的原生支持，但是某些开源框架模拟出了协程的功能，有兴趣的小伙伴可以看一看</span><span
                        class="inline-wrap"><code>Kilim</code></span><span class="inline-wrap">框架的源码：</span><span
                        class="inline-wrap"><a
                            href="https://github.com/kilim/kilim"><span>https://github.com/kilim/kilim</span></a></span>
                </li>
            </ol>
        </div>
        <h2 class="wolai-block"><span class="inline-wrap">参考链接：</span></h2>
        <ul class="wolai-block">
            <li>
                <div class="marker"><svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"
                        xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 14.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z"></path>
                    </svg></div><span class="inline-wrap"><a
                        href="https://zhuanlan.zhihu.com/p/70256971"><span>https://zhuanlan.zhihu.com/p/70256971</span></a></span>
                <div class="wolai-bookmark wolai-block"><a
                        href="https://zhuanlan.zhihu.com/p/70256971">【面试高频问题】线程、进程、协程</a>
                    <div class="info-box">
                        <div class="text-pane">
                            <div data-title="【面试高频问题】线程、进程、协程"></div>
                            <div
                                data-desc="需要先对 IO 的概念有一定的认识: IO在计算机中指Input/Output，也就是输入和输出。 并发与并行 并发：在操作系统中，某一时间段，几个程序在同一个CPU上运行，但在任意一个时间点上，只有一个程序在CPU上运行。 …">
                            </div>
                            <div class="icon-host">
                                <div class="icon icon-image"
                                    style="background-image: url(&quot;https://static.zhihu.com/heifetz/assets/apple-touch-icon-152.a53ae37b.png&quot;)">
                                </div>
                                <div data-hostname="zhuanlan.zhihu.com"></div>
                            </div>
                        </div>
                        <div class="preview-pane"></div>
                    </div>
                </div>
            </li>
        </ul>
        <div class="wolai-block wolai-text">
            <div></div>
        </div>
    </article>
    <footer></footer>
</body>

</html>